/**  protected private public
 * 最简单的单例模式
 */
const _instance = Symbol('_instance');
class User {
  #ids = 123123;
  static [_instance] = null;
  static get getInstance() {
    if (!this[_instance]) {
      this[_instance] = new User();
    }
    return this[_instance];
  }
  #check() {
    console.log('this', this);
    console.log('check私有方法', this.#ids);
  }
  test() {
    this.#check();
  }
}
const uesr = new User();
// uesr.test();
// 使用闭包封装私有变量
const userInfo = (function () {
  let __name = 'sven',
    __age = 29;
  return {
    getUserInfo: function () {
      return __name + '-' + __age;
    },
  };
})();

// 通用性单例
// 创建弹框Model
const getSingleFn = function (fn) {
  let result = void 0;
  return function (...args) {
    // arguments
    return result || (result = fn.apply(this, args));
  };
};

var createLoginLayer = function () {
  var div = document.createElement('div');
  div.innerHTML = '我是登录浮窗';
  div.style.display = 'none';
  document.body.appendChild(div);
  return div;
};

var createSingleLoginLayer = getSingleFn(createLoginLayer);

var loginLayer = createSingleLoginLayer();

document.getElementById('loginBtn').onclick = function () {
  loginLayer.style.display = 'block';
};

//==========代理单例==========
// 渲染类
class CreateDiv {
  constructor(html) {
    this.html = html;
    this.init();
  }
  init() {
    const div = document.createElement('div');
    div.innerText = this.html;
    document.body.appendChild(div);
  }
}

// 代理类
class Render {
  instance = null;
  constructor(html) {
    if (!this.instance) {
      this.instance = new CreateDiv(html);
    }
    return this.instance;
  }
}
const node1 = new Render('hello');
const node2 = new Render('hello-121');
console.log(node1 === node2); // true

// 最好的代理单例模式
function propxySingle(Class) {
  let ins;
  return new Proxy(Class, {
    construct(target, args) {
      if (!ins) {
        ins = new target(...args);
      }
      return ins;
    },
  });
}

// 函数科里化======
function currying(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      // 传入的实参长度 >= 初始函数形参长度 的时候，则直接执行初始函数
      return fn.apply(this, args);
    } else {
      // 否则 得到一个 偏函数，递归carried方法，直到获得所有参数后，直接执行
      return function (...args2) {
        return curried.apply(this, [...args, ...args2]);
      };
    }
  };
}

var currying1 = function (fn) {
  var args = [];
  return function () {
    if (arguments.length === 0) {
      return fn.apply(this, args);
    } else {
      [].push.apply(args, arguments);
      return arguments.callee;
    }
  };
};

var cost = (function () {
  var money = 0;
  return function () {
    for (var i = 0, l = arguments.length; i < l; i++) {
      money += arguments[i];
    }
    return money;
  };
})();

function ke(...args) {
  const cu = function () {
    args = [...args, ...arguments];
    if (!arguments.length) {
      return args.reduce((p, t) => p + t);
    }
    return cu;
  };
  return cu;
}
const new1 = ke();
// console.log(new1(1)(2)(3)(4)(5)());

// let p = new Promise((resolve, reject) => {});
// console.log(Object.prototype.toString.call(p).slice(8, -1));

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// try {
//   aa;
// } catch (error) {
//   // window.location.href = 'https://stackoverflow.com/search?q=[javascript][typescript][node.js]+' + error.message;
//   window.location.href = 'https://stackoverflow.com/search?q=[javascript]+' + error.message;
// }

window.addEventListener('error', (error) => {
  // console.log('error', error);
});
// pageshow事件，pagehide事件: 默认情况下，浏览器会在当前会话(session)缓存页面，当用户点击“前进/后退”按钮时，浏览器就会从缓存中加载页面。

// DOMContentLoaded, readystatechange, pageshow, pagehide, unload, load

// onafterprint: 文档打印之后运行的脚本

// onbeforeprint: 文档打印之前运行的脚本

// onbeforeunload: 文档卸载之前运行的脚本(上文已涉及)

// onerror: 在错误发生时运行的脚本

// onhaschange: 当文档已改变时运行的脚本

// onload: 页面结束加载之后触发(上文已涉及)

// onmessage: 在消息被触发时运行的脚本

// onoffline: 当文档离线时运行的脚本

// ononline: 当文档上线时运行的脚本

// onpagehide: 当窗口隐藏时运行的脚本(上文已涉及)

// onpageshow: 当窗口成为可见时运行的脚本(上文已涉及)

// onpopstate: 当窗口历史记录改变时运行的脚本

// onredo: 当文档执行撤销（redo）时运行的脚本

// onresize: 当浏览器窗口被调整大小时触发

// onstorage: 在 Web Storage 区域更新后运行的脚本

// onundo: 在文档执行 undo 时运行的脚本

// onscroll: 事件在文档或文档元素滚动时执行脚本
